import jwt from 'jsonwebtoken';
import lodash from 'lodash';
import moment from 'moment';
import crypto from 'crypto';
import path from 'path';
import appRoot from 'app-root-path';
import fs from 'fs';
import json2csv from 'json2csv';
import * as x from './data';
import * as institutionCore from '../../sys/institution/core';
import log from '../../../log';
import * as util from '../../../util/';
import {UserType, password} from '../../dict';
import etcConfig from '../../../../etc';

const saltChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const saltCharsLen = saltChars.length;
const globalSalt = 'boco2017';
//const notEqualParms = 'id'.split(',');
const likeParms = 'username,name'.split(',');
/**
 * 生成salt
 * @param {number} l 随机数长度
 */
const generateSalt = (l = 6) => {
    const arr = [];
    const maxLen = saltCharsLen - 1;
    for (let i = 0; i < l; i++) {
        arr.push(saltChars[lodash.random(0, maxLen)]);
    }
    return arr.join('');
};
/*生成密码*/
const generatePw = (pw, salt) => {
    const md5 = crypto.createHash('md5');
    md5.update([lodash.toLower(pw), salt].join(globalSalt));
    return md5.digest('hex');
};

/**获取带分页的列表*/
export function get(pageSize, page, query, user) {
    return util.resolve().then(() => {
        log.info('get user  params----', query);
        log.info('get user  user----', user);
        const pageOpt = {
            page,
            pageSize
        };
        let where = [];
        if (lodash.keys(query).length > 0) {
            lodash.mapKeys(query, (value, key) => {
                if (likeParms.indexOf(key) >= 0) {
                    where.push([`${key}`, 'like', `%${value}%`]);
                } else {
                    where.push([`${key}`, '=', `${value}`]);
                }
            });
        }
        //机构管理员只能看本机构和所有子机构的业务员列表
        if (user.userType === 3) {
            return institutionCore.getAllLevelSonIds(user.institutionId).then(r => {
                where.push(['institutionId', 'in', r]);
                return x.get(where, 1, pageOpt).then(res => {
                    log.info('get users result----', res.toJSON());
                    return util.data(res, 1);
                }).catch(err => {
                    log.error('get users is err', err);
                    throw err;
                });
            });
        }
        if (where.length < 1) {
            where = null;
        }
        return x.get(where, 1, pageOpt).then(res => {
            log.info('get users result----', res.toJSON());
            return util.data(res, 1);
        }).catch(err => {
            log.error('get users is err', err);
            throw err;
        });
    });
}
export function getUser(query, user) {
    return util.resolve().then(() => {
        log.info('getUser users para----', query);
        log.info('get user  user----', user);
        let where = [];
        if (lodash.keys(query).length > 0) {
            lodash.mapKeys(query, (value, key) => {
                if (likeParms.indexOf(key) >= 0) {
                    where.push([`${key}`, 'like', `%${value}%`]);
                } else {
                    where.push([`${key}`, '=', `${value}`]);
                }
            });
        }
        //机构管理员只能看本机构和所有子机构的业务员列表
        if (user.userType === 3) {
            return institutionCore.getAllLevelSonIds(user.institutionId).then(r => {
                where.push(['institutionId', 'in', r]);
                return x.getUser(where, 1).then(res => {
                    log.info('getUser users result----', util.data(res));
                    return util.data(res);
                }).catch(err => {
                    log.error('getUser users is err', err);
                    throw err;
                });
            });
        }
        if (where.length < 1) {
            where = null;
        }
        return x.getUser(where, 1).then(res => {
            log.info('getUser users result----', util.data(res));
            return util.data(res);
        }).catch(err => {
            log.error('getUser users is err', err);
            throw err;
        });
    });
}

/**登录*/
/* eslint no-unused-vars:0*/
export function login({username, password}, ctx) {
    const queryCond = {username};
    // 如果source为app，则认为是app用户；
    //queryCond.userType = source === 'app' ? UserType.app : UserType.default;

    return x.getUserAllColumnsWithRelate([queryCond], 0).then(res => {
        const user = res ? res.toJSON()[0] : undefined;
        log.info('login get user:', user);
        if (!user) {
            //throw '用户不存在';
            return ctx.throw(500, '用户不存在');
        }
        if (user.status !== '1') {
            //throw '用户未启用';
            return ctx.throw(500, '用户未启用');
        }

        if (!user.password) {
            //throw '用户信息不完善';
            return ctx.throw(500, '用户信息不完善');
        }

        const pw = generatePw(password, user.salt);
        if (pw !== user.password) {
            //throw '密码错误';
            return ctx.throw(500, '密码错误');
        }

        const userData = user;
        delete userData.password;
        log.info('log result is1 =----', JSON.stringify(userData));

        return user;
    });
}
/**校验密码*/
function checkPwd(data) {
    return util.resolve().then(() => {
        const {username, password} = data;
        if (!username) throw '校验用户名不能为空';
        if (!password) throw '校验密码不能为空';
        return x.getUserAllColumnsWithRelate([{username}], 0).then(res => {
            const user = res ? res.toJSON()[0] : null;
            if (!user) {
                throw '用户不存在';
            }
            if (user.status !== '1') {
                throw '用户未启用';
            }
            if (!user.password) {
                throw '用户信息不完善';
            }
            const pw = generatePw(password, user.salt);
            if (pw !== user.password) {
                throw '旧密码输入不正确';
            }
            return true;
        });
    });
}
/**修改密码*/
export function changePwd(data) {
    return util.resolve().then(() => {
        if (!data.oldpassword) {
            throw '旧密码不能为空';
        }
        if (data.newpassword !== data.confirmpassword) {
            throw '新密码和确认密码不一致';
        }
        return checkPwd({username: data.username, password: data.oldpassword}).then((res) => {
            if (res) {
                data = lodash.omit(data, 'oldpassword');
                data = lodash.omit(data, 'confirmpassword');
                data.salt = generateSalt();
                data.password = generatePw(data.newpassword, data.salt);
                data = lodash.omit(data, 'newpassword');
                log.info('edit pwd para is ---', data);
                return x.edit(data).then(res => util.result(true, res.toJSON(), 'success', ''));
            }
            return util.result(false, '', '', 'other err!');
        });
    }).catch(err => {
        log.error('changepwd is err', err.message || err);
        throw err;
    });
}
/**新增*/
export function add(user) {
    return x.getUser([{username: user.username}], 0).then(res => {
        const _ = res ? res.toJSON() : [];
        if (_.length > 0) {
            throw Error(`用户名 "${user.username}" 已存在!`);
        }
        const userId = util.uuid();
        user.id = userId;
        user.userType = UserType.default;
        const {password} = user;
        if (password && password.length > 0 && password !== 'defaultPassword') {
            // if (password !== password2 && password !== 'defaultPassword') {
            //     throw Error('两次密码不一致!');
            // }
            // user = lodash.omit(user, 'password2');
            user.salt = generateSalt();
            user.password = generatePw(user.password, user.salt);
        } else {
            throw Error('密码不能为空!');
        }
        log.info('user save data---', user);
        return x.add(user).then(res => {
            log.info('adduser result---', res);
            return userId;
        });
    }).catch(err => {
        log.error('adduser is err', err);
        throw err;
    });
}

/**获取新增用户信息*/
export function getAddInfo(user) {
    return x.getUser([{username: user.username}], 0).then(res => {
        const _ = res ? res.toJSON() : [];
        if (_.length > 0) {
            throw Error(`用户名 "${user.username}" 已存在!`);
        }
        user.id = util.uuid();
        const {password} = user;
        if (password && password.length > 0 && password !== 'defaultPassword') {
            user.salt = generateSalt();
            user.password = generatePw(user.password, user.salt);
        } else {
            throw Error('密码不能为空!');
        }
        return user;
    }).catch(err => {
        log.error('getAddInfo is err', err);
        return err;
    });
}

/**重置机构管理员密码*/
export function resetAdminUserPwd({id}) {
    const user = {};
    user.id = id;
    user.salt = generateSalt();
    user.password = generatePw(password.institution, user.salt);
    return x.edit(user).then(() => {
        return id;
    }).catch(err => {
        log.error('resetAdminUserPwd is err', err);
        return err;
    });
}

/**编辑用户个人信息*/
export function edit(user) {
    log.info('edit user info para---', user);
    return x.getUser([['id', '<>', user.id], ['username', '=', user.username]]).then(res => {
        const _ = res ? res.toJSON() : [];
        if (_.length > 0) {
            throw Error(`用户名 "${user.username}" 已存在!`);
        }
        const {password} = user;
        if (password && password.length > 0 && password !== 'defaultPassword') {
            // if (password !== password2 && password !== 'defaultPassword') {
            //     throw Error('两次密码不一致!');
            // }
            // user = lodash.omit(user, 'password2');
            user.salt = generateSalt();
            user.password = generatePw(user.password, user.salt);
            delete user.password2;
        } else {
            delete user.password;
        }
        log.info('user info save data---', user);
        return x.getUser([{id: user.id}], 0).then(r => {
            const resJson = r ? r.toJSON() : [];
            if (resJson.length > 0) {
                return x.edit(user).then(res => {
                    log.info('edit user info result---', res);
                    return x.getUser([{id: user.id}], 0).then(ret => {
                        ret = ret ? ret.toJSON() : [];
                        return ret[0];
                    });
                });
            }
            throw Error(`未找到用户名 "${user.username}"!`);
        });
    }).catch(err => {
        log.error('edituser is err', err);
        throw err;
    });
}

export function getUserById(id) {
    return x.getUserWithRelate([{id}], 0).then(res => {
        const user = res ? res.toJSON()[0] : undefined;
        log.info('getUserById result---', user);
        return user;
    }).catch(err => {
        log.error('getUserById is err', err);
        throw err;
    });
}
/**修改状态*/
export function editStatus(id, status) {
    return x.edit({id, status})
        .then(res => {
            log.info('editStatus result is ---', res);
            return id;
        })
        .catch(err => {
            log.error('editStatus is err', err);
            throw err;
        });
}
/**删除*/
export function del(id) {
    return x.del(id).then(res => {
        log.info('delete user result ---', res.toJSON());
        return id;
    }).catch(err => {
        log.error('del users is err', err.message || err);
        throw err;
    });
}
export function logOut(ctx) {
    return util.resolve().then(() => {
        log.info('logOut para ---', ctx);
        return null;
    }).catch(err => {
        log.error('logOut is err', err);
        throw err;
    });
}
/**生成token */
export function buildLoginToken(user) {
    const secret = etcConfig.auth || 'secret';
    //默认有效期为7天
    const expiresIn = 60 * 60 * 24 * 7;
    return {
        token: jwt.sign({
            id: user.id,
            name: user.name,
            username: user.username,
            userType: user.userType,
            institutionId: user.institutionId,
            time: new Date().getTime()
        }, secret, {expiresIn}),
        user
    };
}

/**
 * 生成csv文件
 */
function createCsv(data) {
    return util.resolve().then(() => {
        const nowStr = moment().format('YYYYMMDDHHmmss');
        const newFilenName = `业务员数据导出_${nowStr}_${util.randomDigits(4)}.csv`;
        const url = path.join(etcConfig.salesmanCsvExportDir, newFilenName);
        const destFilePath = path.join(appRoot.toString(), url).toString();
        log.info('csv存储path:', destFilePath);

        const fields = [
            {
                label: '工号',
                value: 'code',
                default: ''
            },
            {
                label: '业务员姓名',
                value: 'name',
                default: ''
            },
            {
                label: '业务员手机号',
                value: 'mobile',
                default: ''
            },
            {
                label: '业务员身份证号',
                value: 'idCard',
                default: ''
            },
            {
                label: '所属省',
                value: 'provinceName',
                default: ''
            },
            {
                label: '所属市',
                value: 'cityName',
                default: ''
            },
            {
                label: '所属区',
                value: 'countyName',
                default: ''
            }
        ];
        //log.info('exportCsv salesman fields:', fields);
        return new Promise((resolve, reject) => {
            if (data.length === 0) {
                reject('没有数据');
            }
            return json2csv({data, fields, excelStrings: true, includeEmptyRows: false}, (err, csv) => {
                //将json转为csv格式的buf
                //在写文件之前，转一下编码
                const buf = Buffer.concat([new Buffer('\xEF\xBB\xBF', 'binary'), new Buffer(csv)]);
                return resolve(new Promise((resolve, reject) => {
                    return fs.writeFile(destFilePath, buf, (err) => {
                        if (err) {
                            log.error('exportCsv salesman is err----', err);
                            reject(err);
                        }
                        log.info('exportCsv create file:', destFilePath);
                        resolve(destFilePath);
                    });
                }).then(() => {
                    return {url};
                }));
            });
        });
    }).catch(err => {
        log.error('exportCsv salesman is err----', err);
        return err;
    });
}

export function exportCsv(query, user) {
    return util.resolve().then(() => {
        log.info('exportCsv salesman params----', query);
        log.info('exportCsv salesman user----', user);

        let where = [];
        if (lodash.keys(query).length > 0) {
            lodash.mapKeys(query, (value, key) => {
                if (likeParms.indexOf(key) >= 0) {
                    where.push([`${key}`, 'like', `%${value}%`]);
                } else {
                    where.push([`${key}`, '=', `${value}`]);
                }
            });
        }
        where.push(['name', '<>', '']);
        where.push(['userType', '=', 3]);
        if (where.length < 1) {
            where = null;
        }
        const orderBy = {
            countyId: 'asc',
            cityId: 'asc',
            provinceId: 'asc',
        };
        return x.getUser(where, 1, orderBy).then(r => {
            r = util.data(r);
            return createCsv(r);
        });
    }).catch(err => {
        log.error('exportCsv salesman is err----', err);
        return err;
    });
}

